package com.axialproject.health.exchange.healthvault;

import com.axialproject.health.exchange.EMF;
import com.axialproject.health.exchange.PatientManager;
import com.axialproject.health.exchange.Router;
import com.axialproject.health.exchange.Record;
import com.axialproject.health.exchange.entity.Patient;
import com.microsoft.hsg.ConnectionFactory;
import com.microsoft.hsg.HVAccessor;
import com.microsoft.hsg.Request;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;

public class RouterImpl implements Router {

    private static final Logger log = Logger.getLogger(RouterImpl.class.getName());

    @Override
    public void sendRecord(Patient patient, Record record) {

        log.info ("The patient passed into the HealthVault router: " + patient.getId());
        log.info ("The record passed into HealthVault router is " + record.getDescription());

        // The patient is from the source, we need to find the hvpatient
        Patient hvpatient = null;
        EntityManager em = EMF.get().createEntityManager();
        try {
            List <Patient> patients = PatientManager.getLinkedPatients(em, patient.getId());
            for (Patient p : patients) {
                if ("healthvault".equals(p.getAppName()) && p.getToken() != null && p.getUsername() != null) {
                    boolean validToken = false;
                    
                    // Validate the token and offline patient id
                    validToken = true;

                    if (validToken) {
                        hvpatient = p;
                        break;
                    }
                }
            }

            if (hvpatient == null) {
                log.info ("The healthvault user does not exist or the healthvault token is no longer valid");
                return;
            }
        } catch (Exception e) {
            log.log(Level.SEVERE, e.getMessage(), e);
        } finally {
            em.close ();
        }



        try {

            if (record.getTestNames() != null && record.getTestNames().size() != 0) {
                // Special case 1: BP
                String systolic = "";
                String diastolic = "";
                String pulse = "";
                String irregular = "false";
                for (int i = 0; i < record.getTestNames().size(); i++) {
                    if ("systolic".equals(record.getTestNames().get(i).toLowerCase())) {
                        systolic = record.getTestResults().get(i);
                    }
                    if ("diastolic".equals(record.getTestNames().get(i).toLowerCase())) {
                        diastolic = record.getTestResults().get(i);
                    }
                    if ("pulse".equals(record.getTestNames().get(i).toLowerCase())) {
                        pulse = record.getTestResults().get(i);
                    }
                    if ("irregular".equals(record.getTestNames().get(i).toLowerCase())) {
                        irregular = record.getTestResults().get(i);
                    }
                }
                if (!"".equals(systolic) || !"".equals(diastolic) || !"".equals(pulse)) {
                    Calendar start_calendar = Calendar.getInstance();
                    start_calendar.setTime (record.getStart());
                    String ccdTemplate = readFileAsString("/bp_ccd.xml");
                    String ccdDoc = ccdTemplate.replaceAll("\\#\\{year\\}", Integer.toString(start_calendar.get(Calendar.YEAR)))
                                               .replaceAll("\\#\\{month\\}", Integer.toString(start_calendar.get(Calendar.MONTH) + 1))
                                               .replaceAll("\\#\\{date\\}", Integer.toString(start_calendar.get(Calendar.DATE)))
                                               .replaceAll("\\#\\{hour\\}", Integer.toString(start_calendar.get(Calendar.HOUR_OF_DAY)))
                                               .replaceAll("\\#\\{minute\\}", Integer.toString(start_calendar.get(Calendar.MINUTE)))
                                               .replaceAll("\\#\\{second\\}", Integer.toString(start_calendar.get(Calendar.SECOND)))
                                               .replaceAll("\\#\\{systolic\\}", systolic)
                                               .replaceAll("\\#\\{diastolic\\}", diastolic)
                                               .replaceAll("\\#\\{pulse\\}", pulse)
                                               .replaceAll("\\#\\{irregular\\}", irregular);

                    log.info(ccdDoc);

                    // This is needed for everything ...
                    Request request = new Request();
                    request.setMethodName("PutThings");
                    request.setInfo(ccdDoc);
                    request.setTtl(3600 * 8 + 300);
                    request.setOfflineUserId(hvpatient.getUsername());
                    // request.setUserAuthToken(hvpatient.getToken());
                    request.setRecordId(hvpatient.getRecordId());

                    HVAccessor accessor = new HVAccessor();
                    accessor.send(request, ConnectionFactory.getConnection());
                }

                // Special case 2: Weight
                String weight = "";
                for (int i = 0; i < record.getTestNames().size(); i++) {
                    if ("weight".equals(record.getTestNames().get(i))) {
                        weight = record.getTestResults().get(i);
                    }
                }
                if (!"".equals(weight)) {
                    String weight_lbs = Double.toString(Double.valueOf(weight) * 2.20462262);
                    Calendar start_calendar = Calendar.getInstance();
                    start_calendar.setTime (record.getStart());
                    String ccdTemplate = readFileAsString("/weight_ccd.xml");
                    String ccdDoc = ccdTemplate.replaceAll("\\#\\{year\\}", Integer.toString(start_calendar.get(Calendar.YEAR)))
                                               .replaceAll("\\#\\{month\\}", Integer.toString(start_calendar.get(Calendar.MONTH) + 1))
                                               .replaceAll("\\#\\{date\\}", Integer.toString(start_calendar.get(Calendar.DATE)))
                                               .replaceAll("\\#\\{hour\\}", Integer.toString(start_calendar.get(Calendar.HOUR_OF_DAY)))
                                               .replaceAll("\\#\\{minute\\}", Integer.toString(start_calendar.get(Calendar.MINUTE)))
                                               .replaceAll("\\#\\{second\\}", Integer.toString(start_calendar.get(Calendar.SECOND)))
                                               .replaceAll("\\#\\{kg\\}", weight)
                                               .replaceAll("\\#\\{lb\\}", weight_lbs);

                    // This is needed for everything ...
                    Request request = new Request();
                    request.setMethodName("PutThings");
                    request.setInfo(ccdDoc);
                    request.setTtl(3600 * 8 + 300);
                    request.setOfflineUserId(hvpatient.getUsername());
                    request.setUserAuthToken(hvpatient.getToken());
                    request.setRecordId(hvpatient.getRecordId());

                    HVAccessor accessor = new HVAccessor();
                    accessor.send(request, ConnectionFactory.getConnection());
                }

                // Special case 3: Peak flow

            }
            

            // TODO: manage the return stream


            /*
            String ccrDoc = "<ContinuityOfCareRecord xmlns='urn:astm-org:CCR'>" +
                "<CCRDocumentObjectID>" + UUID.randomUUID().toString() + "</CCRDocumentObjectID>" +
                "<Language><Text>English</Text></Language>" +
                "<Version>V1.0</Version>" +
                "<DateTime><ExactDateTime>" + formatter.format(new Date ()) + "</ExactDateTime></DateTime>" +
                "<Patient><ActorID>" + gpatient.getEmail() + "</ActorID></Patient>" +
                "<Body>";

            // if ("allergy".equals(record.getType())) {
            if (record.getAllergyAllergens() != null && record.getAllergyAllergens().size() != 0) {
                ccrDoc += "<Alerts>";
                String ccrTemplate = readFileAsString("/allergy_ccr.xml");
                for (int i = 0; i < record.getAllergyAllergens().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{severity\\}", record.getAllergySeverities().get(i))
                                            .replaceAll("\\#\\{allergen\\}", record.getAllergyAllergens().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Treating clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Alerts>";
            }

            // if ("testresult".equals(record.getType())) {
            if (record.getTestNames() != null && record.getTestNames().size() != 0) {
                ccrDoc += "<Results>";
                String ccrTemplate = readFileAsString("/testresult_ccr.xml");
                for (int i = 0; i < record.getTestNames().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{test_name\\}", record.getTestNames().get(i))
                                            .replaceAll("\\#\\{test_result\\}", record.getTestResults().get(i))
                                            .replaceAll("\\#\\{test_result_unit\\}", record.getTestResultUnits().get(i))
                                            .replaceAll("\\#\\{test_result_normal_range\\}", record.getTestResultNormalRanges().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Ordering clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Results>";
            }

            if (record.getMedications() != null && record.getMedications().size() != 0) {
                ccrDoc += "<Medications>";
                String ccrTemplate = readFileAsString("/medication_ccr.xml");
                for (int i = 0; i < record.getMedications().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{medication\\}", record.getMedications().get(i))
                                            .replaceAll("\\#\\{medication_dose\\}", record.getMedicationDoses().get(i))
                                            .replaceAll("\\#\\{medication_dose_unit\\}", record.getMedicationDoseUnits().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Prescribing clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Medications>";
            }

            if (record.getConditions() != null && record.getConditions().size() != 0) {
                ccrDoc += "<Problems>";
                String ccrTemplate = readFileAsString("/condition_ccr.xml");
                for (int i = 0; i < record.getConditions().size(); i++) {
                    String ccr = ccrTemplate.replaceAll("\\#\\{start_date\\}", formatter.format(record.getStart()))
                                            .replaceAll("\\#\\{stop_date\\}", formatter.format(record.getStop()))
                                            .replaceAll("\\#\\{condition\\}", record.getConditions().get(i))
                                            .replaceAll("\\#\\{doctor_name\\}", record.getDoctorName())
                                            .replaceAll("\\#\\{doctor_title\\}", "Treating clinician");
                    ccrDoc += ccr;
                }
                ccrDoc += "</Problems>";
            }
            
            ccrDoc += "</Body></ContinuityOfCareRecord>";
            log.info ("CCR content is " + ccrDoc);
            */

        } catch (Exception e) {
            log.log(Level.SEVERE, e.getMessage(), e);
        }
    }

    private String readFileAsString(String fileOnClasspath) throws IOException{
        InputStream is = this.getClass().getResourceAsStream(fileOnClasspath);
        StringBuilder fileData = new StringBuilder(1000);
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            fileData.append(buf, 0, numRead);
        }
        reader.close();
        return fileData.toString();
    }

}
